package view
{
	import flash.utils.Dictionary;
	
	import mx.collections.XMLListCollection;
	import mx.containers.Canvas;
	import mx.controls.Alert;
	import mx.events.CollectionEvent;
	import mx.events.CollectionEventKind;
	import mx.events.FlexEvent;
	import mx.events.PropertyChangeEvent;

	public class BirdsEyeViewCanvas extends Canvas
	{
		private var created:Boolean;
		private var entityIconDictionary:Dictionary = new Dictionary();
		private var numberOfElements:Number = 0;
   	    private var entityCollection:XMLListCollection;

		/**
		 * コンストラクタ．属性の設定と表示が完了した後にonCreationCompleteHandlerが呼び出されるようにします．
		 */
		public function BirdsEyeViewCanvas() {
			trace(this + ":BirdsEyeViewCanvas()");
			this.created = false;
        	addEventListener(FlexEvent.CREATION_COMPLETE, onCreationCompleteHandler, false, 0, true);
			super();
		}

		/*
		 *  Dispatched when the component has finished its construction,
		 *  property processing, measuring, layout, and drawing.
		 */
    	protected function onCreationCompleteHandler(event:FlexEvent):void {
	    	trace(this);
	    	trace("- onCreationCompleteHandler(event=" + event + ")");
    	}
		
		/**
		 * モデルのentity要素のコレクションとバインドさせるためのメソッドです．
		 * UIの親コンポーネントが存在する場合，バインドは複数回発生する可能性があります．
		 */
    	public function set entityProvider(value:XMLListCollection):void {
	   		trace(this + ":entityProvider(value=" + value.toXMLString() + ");");
	        if (this.entityCollection != value) {
	        	if(this.entityCollection) {
	        		trace("- removing this from event listeners of the collection.");
	        		this.entityCollection.removeEventListener(CollectionEvent.COLLECTION_CHANGE,
	        	    	this.entityCollectionChangeHandler);  
	        	}
	        	trace("- adding this to event listeners of the collection.");
			    this.entityCollection = value;
			    this.entityCollection.addEventListener(CollectionEvent.COLLECTION_CHANGE,
	       			this.entityCollectionChangeHandler, false, 0, true);

				trace("- fire fake RESET event");
		        var event:CollectionEvent = new CollectionEvent(CollectionEvent.COLLECTION_CHANGE);
    	    	event.kind = CollectionEventKind.RESET;
	    	    entityCollectionChangeHandler(event);
		    }
    	}
		
	    public function entityCollectionChangeHandler(event:CollectionEvent):void
    	{
       		trace(this + ":collectionChangeHandler(event=" + event + ")");

//       		trace("-> event.currentTarget");
//       		trace(XMLListCollection(event.currentTarget).toXMLString());
//       		trace("<- event.currentTarget");
			
			/**
			 * フレームワークは，コレクションに新しくアイテムが追加したときや削除したときに，
			 * RESETイベントを発生します．
			 * 内部的にはADDやREMOVEも発火しているのですが，
			 * リスナーのつなぎ換えが発生するため，それらのイベントはここには届きません．
			 */
            if (event.kind == CollectionEventKind.RESET)
            {
           		this.resetEntityHandler(event);
              }
            else if (event.kind == CollectionEventKind.ADD)
            {
            	this.addEntityHandler(event);
			}
            else if (event.kind == CollectionEventKind.UPDATE)
            {
            	this.updateEntityHandler(event);
            }

            else if (event.kind == CollectionEventKind.REPLACE)
            {
            }

            else if (event.kind == CollectionEventKind.REMOVE)
            {
            }

            else if (event.kind == CollectionEventKind.MOVE)
            {
            }

            else if (event.kind == CollectionEventKind.REFRESH)
            {
            }
  
//			trace("-> this.entityIconDictionary");
//       		for(var key:String in this.entityIconDictionary) {
//       			trace(this.entityIconDictionary[key]);
//       		}
//			trace("<- this.entityIconDictionary");
    	}

		public function resetEntityHandler(event:CollectionEvent):void {
			//trace(this.entityCollectionAdapter.collection.toXMLString());
           	trace("- RESET");
       		trace("- (re)load all entitiews");
           		
       		for(var key:String in this.entityIconDictionary) {
       			trace("remove id=" + key);
       			this.entityIconDictionary[key] = null;
       			delete this.entityIconDictionary[key]; 
           	}
           		
           	for each(var entity:XML in event.items) {
           		this.addEntity(entity);
           	}
		}

		/**
		 * Entityが追加されたら，画面にEntityアイコンを配置します．
		 */		
		public function addEntityHandler(event:CollectionEvent):void {
           	for each(var entity:XML in event.items) {
	       		this.addEntity(entity);
           	}
    	}
		
		private function addEntity(entity:XML):void {
       		trace("adding new entity to the canvas:", entity.toXMLString());
       		// 新規にエンティティアイコンを生成します
   	   		var entityIcon:EntityIcon = new EntityIcon();
   			entityIcon.entity = entity;
   			// XMLのIDからオブジェクトへの参照テーブルを更新します．
   			this.entityIconDictionary[entity.@id.toString()] = entityIcon;
		}
		
		public function updateEntityHandler(event:CollectionEvent):void {
           	trace("- UPDATE");
           	for each(var pce:PropertyChangeEvent in event.items) {
           		trace("item.source=" + XML(pce.source).toXMLString());
           		trace("item property=" + pce.property + ",newValue=" + pce.newValue);
           		// IDからオブジェクトを探します
           		var entity:XML = XML(pce.source);
           		this.updateEntity(entity);
           	}
		}
		
		private function updateEntity(entity:XML):void {
       		var entityId:String = entity.@id;
       		var entityIcon:EntityIcon = this.entityIconDictionary[entityId];
       		// エンティティアイコンを更新します
       		entityIcon.entity = entity;
		}
		
		public function removeEntityHandler(event:CollectionEvent):void {
           	for each(var entity:XML in event.items) {
	       		trace("removing new entity to the canvas:", entity.toXMLString());
	       		this.removeEntity(entity);
           	}
		}

		private function removeEntity(entity:XML):void {
       		var entityId:String = entity.@id;
       		// TODO: remove()が必要
       		this.entityIconDictionary[entityId] = null;
       		delete this.entityIconDictionary[entityId];
		}
	}
}